#include <Ethernet.h>
#include <WString.h>
#include <ASocket.h>
#include <Client.h>
#include <Server.h>
#include <PString.h>
#include <Dhcp.h>
#include <Dns.h>
#include <string.h>
#include <UdpBytewise.h>

//RTC用ステータスコード
#define RTC_ON_INITIALIZE   	0
#define RTC_ON_SHUTDOWN		1
#define RTC_ON_STARTUP		2
#define RTC_ON_ACTIVATE		3
#define RTC_ON_EXEXCUTE         4
#define RTC_ON_DEACTIVATE	5
#define RTC_ON_ERROR	        6
#define RTC_ON_RESET		7
#define RTC_ON_ABORTING         8

//MAC ID（各シールドに記載）
//byte mac[] = { 0x00, 0x50, 0xC2, 0x97, 0x22, 0x51 };
//byte mac[] = { 0x00, 0x50, 0xC2, 0x97, 0x22, 0x55 };
//byte mac[] = { 0x00, 0x50, 0xC2, 0x97, 0x23, 0x58 };
//byte mac[] = { 0x00, 0x50, 0xC2, 0x97, 0x23, 0x37 };
//byte mac[] = { 0x00, 0x50, 0xC2, 0x97, 0x23, 0x46 };
//byte mac[] = { 0x00, 0x50, 0xC2, 0x97, 0x23, 0x5E };
//byte mac[] = { 0x00, 0x50, 0xC2, 0x97, 0x23, 0x87 };
byte mac[] = { 0x00, 0x50, 0xC2, 0x97, 0x23, 0x8B };
//byte mac[] = { 0x00, 0x50, 0xC2, 0x97, 0x23, 0x3B };
//byte mac[] = { 0x00, 0x50, 0xC2, 0x97, 0x23, 0x40 };
//byte mac[] = { 0x00, 0x50, 0xC2, 0x97, 0x23, 0x47 };
//byte mac[] = { 0x00, 0x50, 0xC2, 0x97, 0x23, 0x4F };

//ipが通ったか
boolean ipAcquired = false;

//サーバIP
byte ip[4];

//受信IP
byte remoteIp[4];

//受信パケットサイズ
int packetSize;

//DNSクラス
DnsClass targetDns;

//ip格納用バッファ
byte buffer[6];

//ポート設定（80：HTTPプロトコル）
Server server(80);

//接続フラグ
boolean connect_flg = false;

//リクエスト格納用文字列
String inString = String(80);

//各センサピン
int ledPin =  2;
int CurrentPin = 0;
int IlumPin = 1;
int TempPin = 2;

void setup(){
  
  //読み取り電圧設定
  analogReference(INTERNAL);
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT); 
  
  Serial.println("getting ip...");
  int result = Dhcp.beginWithDHCP(mac);
  Serial.println(result);
  if(result == 1)
  {
    ipAcquired = true;
    
    Serial.println("ip acquired...");
    
    Dhcp.getMacAddress(buffer);
    Serial.print("mac address: ");
    printArray(&Serial, ":", buffer, 6, 16, false);
    
    Dhcp.getLocalIp(buffer);
    Serial.print("ip address: ");
    //ipアドレスをip[]に格納
    printArray(&Serial, ".", buffer, 4, 10, true);
    
    Dhcp.getSubnetMask(buffer);
    Serial.print("subnet mask: ");
    printArray(&Serial, ".", buffer, 4, 10, false);
    
    Dhcp.getGatewayIp(buffer);
    Serial.print("gateway ip: ");
    printArray(&Serial, ".", buffer, 4, 10, false);
    
    Dhcp.getDhcpServerIp(buffer);
    Serial.print("dhcp server ip: ");
    printArray(&Serial, ".", buffer, 4, 10, false);
    
    Dhcp.getDnsServerIp(buffer);
    Serial.print("dns server ip: ");
    printArray(&Serial, ".", buffer, 4, 10, false);
    
  Serial.println("Ethernet.begin");
  //サーバ開始
  server.begin();
  UdpBytewise.begin(80);
  }
}


void loop(){
  digitalWrite(ledPin, LOW);  
  //
  //UDPゾーン
  //
  
  //コネクト確立フラグが立っていない場合
  if(!connect_flg){
    
    if(packetSize = UdpBytewise.available()) {
      Serial.print("Received packet of size ");
      Serial.println(packetSize);
      
      //送信先のIPをremoteIpに格納
      UdpBytewise.getSenderIp(remoteIp);
      Serial.print("From IP ");
      for(int i=0; i<4; i++) {
        Serial.print(remoteIp[i],DEC);
        if(i<3) Serial.print(".");
      }
      Serial.println("Contents:");
      while(UdpBytewise.available()) {
      Serial.print(UdpBytewise.read(),BYTE);
      }
 
      //送信先ポート1300に返信
      UdpBytewise.beginPacket(remoteIp,1300);
      //MACを送付
      for(int m=0; m<6; m++) {
        UdpBytewise.print(mac[m],HEX);
       if(m<5) UdpBytewise.print("-");
      }
      UdpBytewise.endPacket();
      delay(500);
    }
  }
  
  //wait a bit
  delay(10);  
  
  //
  //HTTPゾーン
  //
  
  //RTCステータスの初期化
  int state = -1;

  //クライアントからのデータ受信
  Client client = server.available();
  
  if (client) {
    digitalWrite(ledPin, HIGH); 
    Serial.println("http access");
    //読み込み用文字列の初期化
    inString=String("");
    boolean blank_line = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        
        inString.append(c);   
        //最初の一行のみ走査
        if (c == '\n') {
         
          //コマンドが含まれているか走査し、ステータスコードを設定
          if(inString.contains("GET")){
            
            //if(inString.contains("INT")){
            //  state = 0;
            //}
            //if(inString.contains("SHT")){
            //  state = 1;
            //}
            //if(inString.contains("STA")){
            //  state = 2;
            //}
            if(inString.contains("ACT")){
              state = 3;
            }
            if(inString.contains("EXE")){
              state = 4;
            }
            if(inString.contains("DEA")){
              state = 5;
            }
            //if(inString.contains("ERR")){
            //  state = 6;
            //}
            //if(inString.contains("RST")){
            //  state = 7;
            //}
            //if(inString.contains("ABT")){
            //  state = 8;
            //}
         
            server.println("HTTP/1.1 200 OK");
            server.println("Content-Type: text/html");
            server.println();         

            //RTC実装関数で残りのヘッダ部分を作成
            RTC_impl(state);
          
            break;
        }
            
          }

      }
    }
    //終了処理
    delay(1);
    client.stop();
  }

}
  
//RTCハンドラの実装
void RTC_impl(int state){
   
  switch (state) {
    case RTC_ON_INITIALIZE:

      break;
    case RTC_ON_SHUTDOWN:

      break;
    case RTC_ON_STARTUP:

      break;
    case RTC_ON_ACTIVATE:
      connect_flg = true;
      break;
 
    case RTC_ON_EXEXCUTE:{
      int SAMPLE_COUNT =30;
      int max_current = 0;
      int current_tmp = 0;
      int temp_sum =0;
      int ilum_sum =0;
      for( int i =0; i <SAMPLE_COUNT; i++){
        //電流値データ
        current_tmp = analogRead(CurrentPin);
        if(max_current < current_tmp){
          max_current = current_tmp;
        }
        //温度データ
        temp_sum +=analogRead(TempPin);
        //照度データ
        ilum_sum +=analogRead(IlumPin);
      }
    
      //平均化  
      int ilum_Value = ilum_sum / SAMPLE_COUNT ;
      int temp_Value = temp_sum / SAMPLE_COUNT ;
      
      //サーバへ書き出し
      server.println(max_current);
      server.println(ilum_Value);
      server.println(temp_Value);
  
      break;
    }
    case RTC_ON_DEACTIVATE:
      connect_flg = false;
      break;
 
    case RTC_ON_ERROR:
    
      break;
    case RTC_ON_RESET:

      break;
    case RTC_ON_ABORTING:

      break;
    default:
      break;
  }
}


//IPadress群を出力するための処理
void printArray(Print *output, char* delimeter, byte* data, int len, int base, boolean flg)
{
  char buf[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};

  for(int i = 0; i < len; i++)
  {
    if(i != 0)
      output->print(delimeter);

    if(flg){ ip[i] = data[i];}
    output->print(itoa(data[i], buf, base));
  }

  output->println();
}
